home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 6
/
QRZ Ham Radio Callsign Database - Volume 6.iso
/
mac
/
files
/
amiga
/
csrc720j.lzh
/
mbrestm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-10
|
11KB
|
532 lines
/*
* MBRESTM - Version 1.61 - 1/20/92
*
* Copyright (C) 1988, 1989, 1990, 1991, 1992
* By the CBBS Group.
*
* This program reads the individual message text files and
* produces MAIL.DAT from the information. It is intended to
* be used after a mail file crash of version 10.
*
* It is expected that this program will be run from the
* directory containing the message files. The new MAIL.DAT
* file will also be found in this directory. It will have to
* copied the the proper bbs directory replacing the corrupted
* original mail file.
*
* MBRESTM when run with any argument will complete itself without
* any operator intervention. i.e. MBRESTM X
*/
#include "mb.h"
#ifndef MCH_AMIGA
#include "dos.h"
#else
#include <libraries/dos.h>
#include <exec/memory.h>
#include <string.h>
#include <stdlib.h>
#endif
MAIL_HDR *mfhs;
MSG_HDR *tmmhs;
byte flds;
char *fld[maxflds];
char *cmd;
char *line;
char *nullstr = "";
#ifndef MCH_AMIGA
char pp[44], name[1000][13], msgfile[10], badfile[10], temp[6];
#else
/* Quick fix for mbrestm on AMIGA. 500 is way too few messages for
any active BBS to try to recover. Our local system had just over
1000 to recover and we're not in a busy QTH! Make it 2000 for now
and hope it is big enough.
*/
#define MAXNUM 2000
char pp[44], name[MAXNUM][13], msgfile[10], badfile[10], temp[5];
#endif
int count = 0;
int cmp();
main(argc, argv)
int argc;
char *argv[];
{
int x, c, y;
int xx = 1;
int recno = 1;
int msgfl, mail;
char *t;
mfhs = (MAIL_HDR *) malloc(sizeof(MAIL_HDR));
tmmhs = (MSG_HDR *) malloc(sizeof(MSG_HDR));
cmd = (char *) malloc(linelen);
line = (char *) malloc(linelen);
printf("Mail Restore Program - Version 1.61\n");
if((mail = open("MAIL.DAT", O_CREAT | O_RDWR | O_BINARY, pmode)) < 0)
{ puts("MAIL.DAT cannot be opened - process aborted!\n");
exit (1);
}
dir_list();
if (count > MAXNUM)
{
printf("Message files greater than %d. Delete some! Aborting\n",MAXNUM);
exit(1);
}
while( xx <= count)
{
y = true;
sprintf (msgfile, "%s",name[xx-1]);
printf("%s ", msgfile);
if((msgfl = open( msgfile, O_RDWR | O_BINARY)) < 0)
{
printf(" cannot be opened - bypassing this file\n");
xx++;
continue;
}
read_rec(msgfl, 0, (char *) line);
if(!((line[253] is '\0') and (line[254] is '\r') and (line[255] is '\n')))
{
printf(" seems to be corrupted - bypassing this file\n");
close(msgfl);
sprintf(badfile, "%s.BAD", msgfile);
rename(msgfile, badfile);
xx++;
continue;
}
fill(temp, '\0', 6);
strncpy(temp, &line[0], 5);
if (atoi(msgfile) != atoi(temp))
{
printf("OLD MSG# [%s] -> Renumbered ", temp);
fill( &line[0], ' ', 5);
sprintf(&line[0],"%5.5s", msgfile);
line[5] = ' ';
write_rec( msgfl, 0, (char*) line);
}
fill(tmmhs, '\0', 256);
tmmhs->rn = xx;
tmmhs->read = atoi( &line[61]);
tmmhs->number = atoi( &line[0]);
tmmhs->size = atoi( &line[9]);
tmmhs->type = line[6];
switch (line[7])
{
case 'O': tmmhs->stat = m_stale; break;
case 'F': tmmhs->stat = m_fwd; break;
case 'H': tmmhs->stat = m_hold; break;
case 'Y': tmmhs->stat = m_read; break;
case 'K': tmmhs->stat = m_kill; break;
case 'B': tmmhs->stat = m_busy; break;
case '$': tmmhs->stat = m_bull; break;
default: tmmhs->stat = '\0';
}
strncpy(tmmhs->to, &line[15], ln_call);
strncpy(tmmhs->from, &line[22], ln_call);
strncpy(tmmhs->bbs, &line[29],ln_call);
strncpy(tmmhs->date, &line[36], ln_date);
strncpy(tmmhs->time, &line[43], ln_time);
#ifdef MCH_AMIGA
/* Recover the lifetime */
tmmhs->lifetime = line[252];
#endif
fill(tmmhs->bid, ' ', ln_bid);
if (line[48] isnt ' ') unbl(tmmhs->bid, &line[48], ln_bid);
tmmhs->ext = line[68] - '0';
if (tmmhs->ext is 1)
{
#ifndef MCH_AMIGA
strncpy(tmmhs->flag, &line[70], mmesn);
#else
strncpy((char *)tmmhs->flag, &line[70], mmesn);
#endif
for( x=0, c=0; x < mmesn; x++, c++)
{
if (tmmhs->flag[x] is ' ') { tmmhs->flag[x] = '0'; c--;}
tmmhs->flag[x] = (tmmhs->flag[x]-'0');
}
tmmhs->count = c;
y = dodis();
}
if (tmmhs->ext is 2)
{
strcpy (cmd, &line[70]);
remnl (cmd);
strcpy(tmmhs->call[0], cmd);
t = strchr(&line[68], '\n');
t++;
strcpy(cmd, t);
remnl(cmd);
strcpy(tmmhs->title, cmd);
}
else
{
parse();
strcpy(tmmhs->title, fld[0]);
}
write_rec(mail,recno++,(char *)tmmhs);
close(msgfl);
if (y) puts("restored");
xx++;
}
mfhs->next = recno;
mfhs->first = 1;
mfhs->last = recno-1;
mfhs->version = mb_version;
mfhs->free = 0;
mfhs->count = recno-1;
mfhs->unt_msg = 1;
fill(mfhs->unu, '\0', mfhsunu);
fill(mfhs->date, '\0', ln_date);
fill(mfhs->time, '\0', ln_time);
x = 1;
if (count) x = 1 + atoi(name[count - 1]);
printf("The next message number will be %u\n", x);
*cmd = 0;
if (argc < 2)
{
printf("Enter return if OK or new message number ");
gets(cmd);
}
if (*cmd) mfhs->next_msg = atoi(cmd);
else mfhs->next_msg = x;
mfhs->unt_msg = mfhs->next_msg;
write_rec(mail, 0, (char *)mfhs);
close(mail);
}
/*
* Parse a command line.
*
* Input: Line of text in line.
* Returns: Fields are placed in cmd.
* Fields are pointed to by fld[].
* flds is set to the number of fields found.
* Each field is null-terminated.
* Fields beyond maxflds are ignored.
*/
parse()
{
char skip;
register short bl;
register char *in, *out;
for (flds = 0; flds < maxflds;)
fld[flds++] = nullstr;
in = &line[86];
out = cmd;
bl = false;
flds = 0;
skip = true;
while (*in and (flds < maxflds) and (out < (cmd + linelen - 1)))
{
#ifndef MCH_AMIGA
if (*in is '\r') { *in++; continue;}
#else
/* Work around a bug in MANX 5.0d compiler (and what a bug!)
The *in++ does not increment in, so as soon as the program finds
a '\r' it hangs in an infinite loop!
*/
if (*in is '\r') { in++; continue;}
#endif
if (*in is '\n') skip = !(skip);
*out = *in;
if (bl) {if ((*in <= ' ') and (skip)) { bl = false; *out = '\0'; } out++; }
else {if (*in > ' ') { bl = true; fld[flds++] = out++; }}
in++;
}
*out = '\0';
}
/*
* Remove new line and carriage returns from end of string.
*/
remnl(p)
char *p;
{
for (; *p; p++)
{
if ((*p is '\n') or (*p is '\r')) { *p = '\0'; return; }
}
}
/*
* Read random record.
*/
read_rec(fid, rec, buffer)
int fid;
int rec;
char buffer[];
{
#ifndef MCH_AMIGA
long lseek();
#endif
long offs;
offs = (long)rec * (long)RECSIZE;
lseek(fid, offs, 0);
return (read(fid, buffer, RECSIZE) is RECSIZE);
}
/*
* Write random record.
*/
write_rec(fid, rec, buffer)
int fid;
int rec;
char buffer[];
{
#ifndef MCH_AMIGA
long lseek();
#endif
long offs;
offs = (long)rec * (long)RECSIZE;
lseek(fid, offs, 0);
return (write(fid, buffer, RECSIZE) is RECSIZE);
}
/*
* Fill some memory with a character.
*/
fill(adr, ch, len)
char *adr;
char ch;
int len;
{
while (len--) *adr++ = ch;
}
/*
* Create the distribution list, if required.
*/
dodis()
{
register FILE *dfl;
char c;
char tmp[linelen];
tmmhs->ext = 0;
if (*tmmhs->bbs is ' ') return;
unbl(tmp, tmmhs->bbs, ln_call);
strcat( tmp, ".DIS");
if ((dfl = fopen( tmp, "r")) is NULL)
{
printf("restored without %s (file is not found)\n", tmp);
return false;
}
tmmhs->ext = 0x01;
for (c = 0; (c <tmmhs->count) and (fgets( tmp, linelen, dfl) isnt NULL);
c++)
{
strupr(tmp);
pcall(tmmhs->call[c], tmp);
}
fclose(dfl);
return true;
}
/*
* Copy LJSF string to C string.
*/
unbl(to, from, size)
char *to, *from;
int size;
{
while (size--)
{
if (*from <= ' ') { *to = '\0'; return; }
*to++ = *from++;
}
*to = '\0';
}
/*
* Parse a callsign.
* Blank pad the output field, remove trailing ssid from call.
* Return the SSID.
*/
pcall(c, p)
char *c;
char *p;
{
register short i;
/*
* Blank fill the target buffer.
*/
fill (c, ' ', ln_call);
/*
* Ignore leading spaces.
*/
while (*p and (*p is ' ')) p++;
/*
* Copy the call from the string into the call buffer.
*/
for (i = ln_call; i and *p; i--)
{
if (*p <= ' ') return 0;
if (*p is '-') return atoi(++p);
*c++ = *p++;
}
if (*p++ is '-') return atoi(p); else return 0;
}
/*
* Read the file names from the current directory and store
* the results in an array but exclude any name that is not
* made up of all numbers.
* Sort the resulting list in ascending order.
*/
#ifndef MCH_AMIGA
dir_list()
{
int x, y;
char *file_name = "*.";
printf("Reading directory - ");
bdos(0x1a, (unsigned)pp, 0);
if(18==bdos(0x4e, (unsigned)file_name, 0))
{
printf("No message files are found\n");
return;
}
if (num( &pp[30])) strcpy (name[count++], &pp[30]);
for(;;)
{
if(18==bdos(0x4f, 0, 0)) break;
if (num( &pp[30])) strcpy (name[count++], &pp[30]);
}
#else
/*
* A directory item looks like this:
struct FileInfoBlock {
LONG fib_DiskKey;
LONG fib_DirEntryType;
char fib_FileName[108];
LONG fib_Protection;
LONG fib_EntryType;
LONG fib_Size;
LONG fib_NumBlocks;
struct DateStamp fib_Date;
char fib_Comment[80];
char padding[36];
};
*/
typedef struct FileInfoBlock FCB;
static FCB *fcb = 0;
/*
* Open directory and create list of numeric files.
*/
long lock;
extern long Examine(),Lock(),ExNext();
dir_list()
{
int x, y;
long result,Info();
fcb = (FCB *)AllocMem((long)sizeof(*fcb),MEMF_PUBLIC|MEMF_CLEAR);
/*
* Get a lock on the current directory
*/
lock = Lock((UBYTE *)"",ACCESS_READ);
if(lock == 0L) {
return;
}
/* and examine it to make sure it's OK */
if((result = Examine(lock,fcb)) == 0L) {
UnLock(lock);
return;
}
for(;;) {
/* Get next directory entry */
if(ExNext(lock,fcb) == 0L) {
UnLock(lock);
break;
}
/* If the entry is a directory, go back for another */
if(fcb->fib_DirEntryType > 0)continue;
/* If the filename is numeric then add it into the list */
if(num(fcb->fib_FileName)) {
strcpy (name[count++], &fcb->fib_FileName[0]);
if(count >= MAXNUM) {
printf("Sorry - I can't handle more than %d entries\n",MAXNUM);
printf("Try deleting some of the older message numbers\n");
printf("manually and then try mbrestm again\n");
UnLock(lock);
FreeMem(fcb,(long)sizeof(*fcb));
exit(1);
}
}
}
FreeMem(fcb,(long)sizeof(*fcb));
#endif
printf("There are %d message files\n", count);
if (count)
{
printf("***Sorting***\n");
qsort (name, count, 13, cmp);
for(x=0, y=1; x< count; x++, y++)
{
printf("%6s", name[x]);
if(y is 10) { printf("\n"); y=0; }
}
printf("\n");
}
}
/*
* Compare two strings converted to integers.
*/
int cmp(n1,n2)
char *n1;
char *n2;
{
return (atoi(n1) - atoi(n2));
}
/*
* Is the string a number?
*/
num(p)
char *p;
{
for (; *p; p++) if (!isdigit(*p)) return false;
return true;
}